﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using MediaPortal.Configuration;
using MediaPortal.Dialogs;
using MediaPortal.GUI.Library;
using MediaPortal.Profile;

namespace Translator
{
    [PluginIcons("Translator.Translator.png", "Translator.TranslatorDisabled.png")]
    public class GuiTranslator : GUIWindow, ISetupForm, IShowPlugin
    {
        #region ISetupForm Member

        public string Author()
        {
            return "offbyone";
        }

        public bool CanEnable()
        {
            return true;
        }

        public bool DefaultEnabled()
        {
            return true;
        }

        public string Description()
        {
            return "Translate or define a given word.";
        }

        public bool GetHome(out string strButtonText, out string strButtonImage, out string strButtonImageFocus, out string strPictureImage)
        {
            strButtonText = "Translator";
            strButtonImage = String.Empty;
            strButtonImageFocus = String.Empty;
            strPictureImage = @"hover_Translator.png";
            return true;
        }

        public int GetWindowId()
        {
            return GetID;
        }

        public bool HasSetup()
        {
            return false;
        }

        public string PluginName()
        {
            return "Translator";
        }

        public void ShowPlugin()
        {
            
        }

        #endregion

        #region IShowPlugin Member

        public bool ShowDefaultHome()
        {
            return false;
        }

        #endregion

        #region Skin Controls

        [SkinControlAttribute(47561)]
        protected GUIButtonControl btnLookupWord = null;
        [SkinControlAttribute(47562)]
        protected GUIFadeLabel lblWord = null;
        [SkinControlAttribute(47563)]
        protected GUISelectButtonControl btnSourceLang = null;
        [SkinControlAttribute(47564)]
        protected GUISelectButtonControl btnTargetLang = null;
        [SkinControlAttribute(47565)]
        protected GUISelectButtonControl btnProvider = null;
        [SkinControlAttribute(50)]
        protected GUIFacadeControl facade = null;
        
		#endregion

		#region Fields

		Dictionary<string, ITranslationProvider> providers = new Dictionary<string, ITranslationProvider>();
		string selectedProvider;
		string selectedSourceLang;
		string selectedTargetLang;
		string lastTranslatedWord = "";
		List<Term> lastTranslationResult;
		
		#endregion

		#region Constants

		public const int WINDOW_ID = 4756;
		public const string CONFIG_SECTION = "myTranslator";
		
		#endregion

		#region GUIWindow Overriddes

		public override int GetID
        {
			get { return WINDOW_ID; }
            set { base.GetID = value; }
        }

        public override bool Init()
        {
            bool result = Load(GUIGraphicsContext.Skin + @"\myTranslator.xml");
			selectedProvider = MPSettings.Instance.GetValue(CONFIG_SECTION, "provider");
            return result;
        }

        protected override void OnPageLoad()
        {
            base.OnPageLoad(); // let animations run

			if (lblWord != null) lblWord.Label = lastTranslatedWord;
			if (facade != null && lastTranslationResult != null)
            {
                foreach (Term term in lastTranslationResult)
                {
                    GUIListItem item = new GUIListItem(term.Lang1);
                    item.Label2 = term.Lang2;
                    item.RetrieveArt = false;
                    facade.Add(item);
                }
            }

            if (providers.Count == 0)
            {
                foreach (var provider in this.GetType().Assembly.GetExportedTypes().Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(typeof(ITranslationProvider))))
                {
                    providers.Add(provider.Name.Replace("Provider", ""), Activator.CreateInstance(provider) as ITranslationProvider);
                }
				if (string.IsNullOrEmpty(selectedProvider) || !providers.Any(p => p.Key == selectedProvider))
				{
					selectedProvider = providers.Count > 0 ? providers.First().Key : null;
				}
            }

            if (btnProvider != null && btnProvider.SubItemCount == 0)
            {
                int i = 0;
                foreach (var provider in providers)
                {
                    GUIControl.AddItemLabelControl(GetID, btnProvider.GetID, provider.Key);
                    if (provider.Key == selectedProvider)
                    {
                        btnProvider.SelectedItem = i;
                        btnProvider.Label = selectedProvider;
                        SetLanguagesToSelectButtons();
                    }
                    i++;
                }
            }

			if (!string.IsNullOrEmpty(base._loadParameter))
			{
				lastTranslatedWord = base._loadParameter;
				Translate();
			}
        }

        public override bool OnMessage(GUIMessage message)
        {
            bool m = base.OnMessage(message);
            
            if (btnProvider != null && message.TargetControlId == btnProvider.GetID)
            {
                if (btnProvider.SelectedLabel != selectedProvider)
                {
                    for (int i = 0; i < providers.Count; i++) if (providers.ElementAt(i).Key == selectedProvider) btnProvider.SelectedItem = i;
                    btnProvider.Label = selectedProvider;
                }
            }
            else if (btnSourceLang != null && message.TargetControlId == btnSourceLang.GetID)
            {
                if (btnSourceLang.SelectedLabel != btnSourceLang.Label)
                {
                    btnSourceLang.SelectedItem = Array.FindIndex<string>(providers[selectedProvider].SourceLanguages, l => l == selectedSourceLang);
                    btnSourceLang.Label = selectedSourceLang;
                }
            }
            else if (btnTargetLang != null && message.TargetControlId == btnTargetLang.GetID)
            {
                if (btnTargetLang.SelectedLabel != btnTargetLang.Label)
                {
                    btnTargetLang.SelectedItem = Array.FindIndex<string>(providers[selectedProvider].TargetLanguages, l => l == selectedTargetLang);
                    btnTargetLang.Label = selectedTargetLang;
                }
            }

            return m;
        }

        protected override void OnClicked(int controlId, GUIControl control, MediaPortal.GUI.Library.Action.ActionType actionType)
        {
            if (control == btnLookupWord)
            {
                if (GetUserInputString(ref lastTranslatedWord))
                {
					Translate();
                }
            }
            else if (control == btnProvider)
            {
                selectedProvider = btnProvider.SelectedLabel;
                btnProvider.Label = selectedProvider;
                SetLanguagesToSelectButtons();
            }
            else if (control == btnSourceLang)
            {
                selectedSourceLang = btnSourceLang.SelectedLabel;
                btnSourceLang.Label = btnSourceLang.SelectedLabel;
				MPSettings.Instance.SetValue(CONFIG_SECTION, string.Format("{0}#{1}", selectedProvider, "SourceLang"), selectedSourceLang);
            }
            else if (control == btnTargetLang)
            {
                selectedTargetLang = btnTargetLang.SelectedLabel;
                btnTargetLang.Label = btnTargetLang.SelectedLabel;
				MPSettings.Instance.SetValue(CONFIG_SECTION, string.Format("{0}#{1}", selectedProvider, "TargetLang"), selectedTargetLang);
            }
            base.OnClicked(controlId, control, actionType);
        }

		#endregion

		private void Translate()
		{
			lblWord.Label = lastTranslatedWord;
			facade.Clear();
			lastTranslationResult = null;

			GUIWaitCursor.Init();
			GUIWaitCursor.Show();
			BackgroundWorker worker = new BackgroundWorker();
			worker.DoWork += new DoWorkEventHandler(delegate(object o, DoWorkEventArgs e)
			{
				try
				{
					List<Term> terms = new List<Term>();
					string error = null;
					if (providers[selectedProvider].Translate(lastTranslatedWord, selectedSourceLang, selectedTargetLang, out terms, out error))
					{
						e.Result = terms;
					}
					else
					{
						e.Result = error;
					}
				}
				catch (Exception ex)
				{
					e.Result = ex.Message;
				}
			});
			worker.RunWorkerCompleted += OnBackGroundTaskDone;
			worker.RunWorkerAsync();
		}

        void SetLanguagesToSelectButtons()
        {
			MPSettings.Instance.SetValue(CONFIG_SECTION, "provider", selectedProvider);

			// restore selected source and target language
			string temp = MPSettings.Instance.GetValue(CONFIG_SECTION, string.Format("{0}#{1}", selectedProvider, "SourceLang"));
			if (!string.IsNullOrEmpty(temp)) selectedSourceLang = temp;
			temp = MPSettings.Instance.GetValue(CONFIG_SECTION, string.Format("{0}#{1}", selectedProvider, "TargetLang"));
			if (!string.IsNullOrEmpty(temp)) selectedTargetLang = temp;

            int i = 0;
            if (btnSourceLang != null)
            {
                btnSourceLang.Clear();
                foreach (var lang in providers[selectedProvider].SourceLanguages)
                {
                    if (lang == selectedSourceLang) i = btnSourceLang.SubItemCount;
                    GUIControl.AddItemLabelControl(GetID, btnSourceLang.GetID, lang);
                }
                btnSourceLang.SelectedItem = i;
                btnSourceLang.Label = btnSourceLang.SelectedLabel;
                selectedSourceLang = btnSourceLang.SelectedLabel;
            }
            i = 0;
            if (btnTargetLang != null)
            {
                btnTargetLang.Clear();
                foreach (var lang in providers[selectedProvider].TargetLanguages)
                {
                    if (lang == selectedTargetLang) i = btnTargetLang.SubItemCount;
                    GUIControl.AddItemLabelControl(GetID, btnTargetLang.GetID, lang);
                }
                btnTargetLang.SelectedItem = i;
                btnTargetLang.Label = btnTargetLang.SelectedLabel;
                selectedTargetLang = btnTargetLang.SelectedLabel;
            }
        }

        void OnBackGroundTaskDone(object sender, RunWorkerCompletedEventArgs e)
        {
            GUIWaitCursor.Hide();

            if (e.Result is string) ShowMessage(e.Result as string);
            else if (e.Result == null) ShowMessage("No results!");
            else if (e.Result is List<Term>)
            {
                if ((e.Result as List<Term>).Count == 0) ShowMessage("No results!");
                else
                {
                    lastTranslationResult = e.Result as List<Term>;
                    foreach (Term term in e.Result as List<Term>)
                    {
                        GUIListItem item = new GUIListItem(term.Lang1);
                        item.Label2 = term.Lang2;
                        item.RetrieveArt = false;
                        facade.Add(item);
                    }
                    GUIControl.FocusControl(GetID, facade.GetID);
                }
            }
        }

        bool GetUserInputString(ref string input)
        {
            VirtualKeyboard keyBoard = (VirtualKeyboard)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_VIRTUAL_KEYBOARD);
            keyBoard.Reset();
            keyBoard.IsSearchKeyboard = true;
            keyBoard.Text = input;
            keyBoard.DoModal(GetID);
            GUIWindowManager.Process();
            if (keyBoard.IsConfirmed) input = keyBoard.Text;
            return keyBoard.IsConfirmed;
        }

        void ShowMessage(string message)
        {
            GUIDialogNotify dlg = (GUIDialogNotify)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_NOTIFY);
            if (dlg != null)
            {
                dlg.Reset();
                dlg.SetImage(GUIGraphicsContext.Skin + @"\Media\myTranslator.png");
                dlg.SetHeading("Translator");
                dlg.SetText(message);
                dlg.DoModal(GUIWindowManager.ActiveWindow);
            }
        }
    }
}
